﻿using LightCAD.Core;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LightCAD.MathLib;

namespace LightCAD.Runtime
{
    public struct Bounds
    {
        /// <summary>
        /// Center
        /// </summary>
        public Vector2 Center
        {
            get
            {
                return new Vector2(
                    (_left + _right) / 2.0,
                    (_bottom + _top) / 2.0);
            }
        }

        /// <summary>
        /// Width
        /// </summary>
        private double _width;
        public double Width
        {
            get { return _width; }
            //set { _width = value; }
        }

        /// <summary>
        /// Height
        /// </summary>
        private double _height;
        public double Height
        {
            get { return _height; }
            //set { _height = value; }
        }

        /// <summary>
        /// Left
        /// </summary>
        private double _left;
        public double Left
        {
            get { return _left; }
        }

        /// <summary>
        /// Right
        /// </summary>
        private double _right;
        public double Right
        {
            get { return _right; }
        }

        /// <summary>
        /// Top
        /// </summary>
        private double _top;
        public double Top
        {
            get { return _top; }
        }

        /// <summary>
        /// Bottom
        /// </summary>
        private double _bottom;
        public double Bottom
        {
            get { return _bottom; }
        }

        /// <summary>
        /// Constructor
        /// </summary>
        public Bounds(Vector2 point1, Vector2 point2)
        {
            if (point1.X < point2.X)
            {
                _left = point1.X;
                _right = point2.X;
            }
            else
            {
                _left = point2.X;
                _right = point1.X;
            }

            if (point1.Y < point2.Y)
            {
                _bottom = point1.Y;
                _top = point2.Y;
            }
            else
            {
                _bottom = point2.Y;
                _top = point1.Y;
            }

            _width = _right - _left;
            _height = _top - _bottom;
        }
        public Bounds(double left, double top, double width, double height)
        {
            _left = left;
            _top = top;
            _width = width;
            _height = height;
            _right = left+width;
            _bottom = top+height;
        }
        public Bounds(Vector2 center, double width, double height)
        {
            _left = center.X - width / 2.0;
            _right = center.X + width / 2.0;
            _bottom = center.Y - height / 2.0;
            _top = center.Y + height / 2.0;
            _width = _right - _left;
            _height = _top - _bottom;
        }

        /// <summary>
        /// Check whether contains bounding
        /// </summary>
        public bool Contains(Bounds bounds)
        {
            return this.Contains(bounds.Left, bounds.Bottom)
                && this.Contains(bounds.Right, bounds.Top);
        }

        /// <summary>
        /// Check whether contains point
        /// </summary>
        public bool Contains(Vector2 point)
        {
            return this.Contains(point.X, point.Y);
        }

        /// <summary>
        /// Check whether contains point: (x, y)
        /// </summary>
        public bool Contains(double x, double y)
        {
            return x >= this._left
                && x <= this._right
                && y >= this._bottom
                && y <= this._top;
        }

        /// <summary>
        /// Check whether intersect with bounding
        /// </summary>
        public bool IntersectWith(Bounds bounds)
        {
            bool b1 = (bounds.Left >= this.Left && bounds.Left <= this.Right)
                || (bounds.Right >= this.Left && bounds.Right <= this.Right)
                || (bounds.Left <= this.Left && bounds.Right >= this.Right);

            if (b1)
            {
                bool b2 = (this._bottom >= bounds.Bottom && this._bottom <= bounds.Top)
                    || (this._top >= bounds.Bottom && this._top <= bounds.Top)
                    || (this._bottom <= this.Bottom && this._top >= bounds.Top);
                if (b2)
                {
                    return true;
                }
            }


            return false;
        }

        public SKRect ToSKRect()
        {
            return new SKRect((float)this.Left, (float)this.Top, (float)this.Right, (float)this.Bottom);
        }
        
    }
}
